<template>
  <el-form
    ref="dynamicForm"
    :model="formModel"
    :rules="formRules"
    :inline="formConfig.inline"
    :label-position="formConfig.labelPosition"
    label-width="100px"
    @submit.prevent="handleSave"
    class="dynamic-form"
  >
    <template v-for="(field, index) in formConfig.fields" :key="index">
      <!-- 分隔符 -->
      <el-divider v-if="field.type === 'divider'" :content-position="field.position || 'center'">
        {{ field.label || '' }}
      </el-divider>

      <!-- 纯文本内容 -->
      <template v-else-if="field.type === 'plaintext'">
        <p class="form-plaintext" :style="field.style">{{ field.content }}</p>
      </template>

      <el-form-item v-else :label="field.label" :prop="field.model">
        <!-- 动态生成通用组件 -->
        <component
          v-if="field.type !== 'table' && field.type !== 'daterange'"
          :is="getComponentType(field.type)"
          v-model="formModel[field.model]"
          v-bind="field"
          :maxlength="field.maxlength"
          :show-word-limit="!!field.maxlength"
        >
          <!-- 下拉框选项 -->
          <el-option
            v-if="field.type === 'select'"
            v-for="option in field.options"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
          <!-- 单选框选项 -->
          <template v-if="field.type === 'radio'">
            <el-radio-group v-model="formModel[field.model]">
              <el-radio v-for="option in field.options" :key="option.value" :value="option.value">
                {{ option.label }}
              </el-radio>
            </el-radio-group>
          </template>
          <!-- 多选框选项 -->
          <template v-if="field.type === 'checkbox'">
            <el-checkbox-group v-model="formModel[field.model]">
              <el-checkbox v-for="option in field.options" :key="option.value" :value="option.value">
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
          </template>
        </component>

        <!-- 日期范围选择器 -->
        <el-date-picker
          v-if="field.type === 'daterange'"
          v-model="formModel[field.model]"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          style="width: 100%"
        ></el-date-picker>

        <!-- 表格组件 -->
        <div v-if="field.type === 'table'" style="width: 100%">
          <el-table :data="formModel[field.model]" style="width: 100%" border>
            <el-table-column
              v-for="(column, colIndex) in field.columns"
              :key="colIndex"
              :prop="column.prop"
              :label="column.label"
              :width="column.width || 'auto'"
            >
              <template #default="scope">
                <el-input
                  v-if="column.type === 'text'"
                  v-model="scope.row[column.prop]"
                  placeholder="请输入内容"
                  style="width: 100%"
                ></el-input>
                <el-input-number
                  v-else-if="column.type === 'number'"
                  v-model="scope.row[column.prop]"
                  style="width: 100%"
                ></el-input-number>
              </template>
            </el-table-column>
          </el-table>

          <!-- 添加新行按钮 -->
          <el-button type="primary" size="small" @click="addTableRow(field.model)"> 添加新行 </el-button>
          <!-- 删除空白行按钮 -->
          <el-button type="danger" size="small" @click="removeEmptyRows(field.model)"> 删除空白行 </el-button>
        </div>
      </el-form-item>
    </template>

    <el-form-item>
      <el-button type="primary" @click="handleSave">保存</el-button>
      <el-button type="default" @click="handleLoad">加载数据</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  data() {
    return {
      formConfig: {
        inline: false,
        labelPosition: 'right',
        fields: []
      },
      formModel: {},
      formRules: {}
    };
  },
  watch: {
    // 动态监听所有字段变化，触发总和计算
    formModel: {
      handler() {
        this.calculateSum();
      },
      deep: true
    }
  },
  methods: {
    initForm(config) {
      this.formConfig = config;
      this.formModel = {};
      this.formRules = {};

      // 根据配置生成初始值和校验规则
      config.fields.forEach((field) => {
        if (field.type === 'checkbox') {
          // 初始化多选框
          this.formModel[field.model] = field.defaultValue || [];
        } else if (field.type === 'daterange') {
          // 初始化日期范围选择器
          this.formModel[field.model] = field.defaultValue || [];
        } else if (field.type === 'table') {
          // 初始化表格数据并添加默认行
          const defaultRowCount = field.defaultRowCount || 0;
          this.formModel[field.model] = Array.from({ length: defaultRowCount }, () => {
            const row = {};
            field.columns.forEach((column) => {
              row[column.prop] = column.type === 'number' ? null : '';
            });
            return row;
          });
        } else {
          this.formModel[field.model] = field.defaultValue || '';
        }

        if (field.rules) {
          this.formRules[field.model] = field.rules;
        }
      });
    },
    getComponentType(type) {
      const componentMap = {
        text: 'el-input',
        textarea: 'el-input',
        number: 'el-input-number',
        select: 'el-select',
        radio: 'el-radio-group',
        checkbox: 'el-checkbox-group',
        date: 'el-date-picker'
      };
      return componentMap[type] || 'el-input';
    },
    handleSave() {
      // 删除空白行
      this.formConfig.fields.forEach((field) => {
        if (field.type === 'table') {
          this.removeEmptyRows(field.model);
        }
      });

      this.$refs.dynamicForm.validate((valid) => {
        if (valid) {
          console.log('保存成功：', this.formModel);
        } else {
          console.log('校验失败');
          this.$message({
            type: 'error',
            message: '必填项不能为空'
          });
        }
      });
    },
    calculateSum() {
      // 遍历带有 sum 标记的字段，计算总和
      const total = this.formConfig.fields
        .filter((field) => field.sum)
        .reduce((acc, field) => acc + (parseFloat(this.formModel[field.model]) || 0), 0);

      // 查找求和结果字段并更新
      const sumTargetField = this.formConfig.fields.find((field) => field.sumTarget);
      if (sumTargetField) {
        this.formModel[sumTargetField.model] = total;
      }
    },
    handleLoad() {
      // 加载示例数据
      const mockData = {
        name: '李四',
        remark: '这是一个示例表单',
        gender: '男',
        age: 25,
        hobbies: ['篮球', '音乐'],
        city: '上海',
        birthDate: '2000-05-01',
        idDate: ['2023-01-01', '2033-12-31'],
        tableData: [
          { name: '李四', age: 25, job: '工程师' },
          { name: '王五', age: 28, job: '工程师' }
        ]
      };
      Object.assign(this.formModel, mockData);
    },
    addTableRow(model) {
      this.formModel[model].push({ name: '', age: null, job: '' });
    },
    removeEmptyRows(model) {
      const tableData = this.formModel[model];
      this.formModel[model] = tableData.filter((row) => {
        return Object.values(row).some((value) => value !== '' && value !== null && value !== undefined);
      });
    }
  },
  mounted() {
    // 初始化表单
    const formConfig = {
      inline: false, // 是否行内表单
      labelPosition: 'top', // 标签位置
      fields: [
        {
          type: 'text',
          label: '姓名',
          model: 'name',
          maxlength: 20, // 设置文本框的最大长度 ==> 0：不限制长度
          placeholder: '请输入姓名',
          rules: [{ required: true, message: '姓名不能为空', trigger: 'blur' }], // 添加校验规则
          defaultValue: '张三' // 设置默认值
        },
        {
          type: 'textarea',
          label: '备注',
          model: 'remark',
          maxlength: 0,
          placeholder: '请输入备注',
          rows: 3, // 设置多行文本框的行数
          defaultValue: '这是一个表单\n多行表单测试'
        },
        {
          type: 'radio',
          label: '性别',
          model: 'gender',
          options: [
            { label: '男', value: '男' },
            { label: '女', value: '女' }
          ],
          defaultValue: '男'
        },
        {
          type: 'number',
          label: '年龄',
          model: 'age',
          placeholder: '请输入年龄',
          defaultValue: 15
        },
        {
          type: 'date',
          label: '出生日期',
          model: 'birthDate',
          placeholder: '选择日期',
          defaultValue: new Date('2000-01-01')
        },
        {
          type: 'daterange',
          label: '身份证有效期',
          model: 'idDate',
          placeholder: '选择日期范围',
          defaultValue: ['2020-01-01', '2030-12-31']
        },
        {
          type: 'divider',
          label: '分隔符',
          position: 'left'
        },
        {
          type: 'checkbox',
          label: '兴趣爱好',
          model: 'hobbies',
          options: [
            { label: '足球', value: '足球' },
            { label: '篮球', value: '篮球' },
            { label: '音乐', value: '音乐' }
          ],
          defaultValue: ['足球', '音乐']
        },
        {
          type: 'select',
          label: '城市',
          model: 'city',
          options: [
            { label: '北京', value: '北京' },
            { label: '上海', value: '上海' }
          ],
          defaultValue: '北京'
        },
        {
          type: 'plaintext',
          content: '这是一个纯文本内容，仅用于提示。',
          style: 'color: #409eff;' // 自定义样式
        },
        {
          type: 'table',
          label: '数据表格',
          model: 'tableData',
          defaultRowCount: 3, // 默认空行数
          columns: [
            { label: '姓名', prop: 'name', type: 'text' },
            { label: '年龄', prop: 'age', type: 'number' },
            { label: '职业', prop: 'job', type: 'text' }
          ]
        },
        {
          type: 'number',
          label: '数字1',
          model: 'sum1',
          placeholder: '请输入'
          // defaultValue: 0,
          // sum: true, // 标记为需要参与求和
        },
        {
          type: 'number',
          label: '数字2',
          model: 'sum2',
          placeholder: '请输入',
          // defaultValue: 0,
          sum: true
        },
        {
          type: 'number',
          label: '数字3',
          model: 'sum3',
          placeholder: '请输入',
          // defaultValue: 0,
          sum: true
        },
        {
          type: 'number',
          label: '总和',
          model: 'totalSum',
          placeholder: '自动计算',
          readonly: true, // 总和字段只读
          sumTarget: true // 标记为求和结果字段
        }
      ]
    };
    this.initForm(formConfig);
  }
};
</script>

<style>
/* 行内表单隐藏 label */
.dynamic-form.el-form--inline .el-form-item .el-form-item__label {
  width: 0;
  display: none;
}

/* 行内表单设置间距 */
.dynamic-form.el-form--inline .el-form-item {
  margin: 0 2px;
}

/* 行内表单下拉框最小宽度 */
.dynamic-form.el-form--inline .el-form-item .el-select {
  min-width: 150px;
}

/* 表单内纯文本 */
.form-plaintext {
  font-size: 14px;
  display: inline-flex;
  vertical-align: middle;
  margin: 0 0 18px 0;
  align-items: center;
  line-height: 32px;
  min-width: 0;
}

/* 行内表单内纯文本间距 */
.dynamic-form.el-form--inline .form-plaintext {
  margin: 0 2px;
}
</style>

<style scoped></style>
